package com.gcloud.controller.compute.dao;

import com.gcloud.controller.compute.entity.ComputeNode;
import com.gcloud.controller.compute.model.node.DescribeNodesParams;
import com.gcloud.controller.compute.model.vm.DescribeMigrateNodesParams;
import com.gcloud.framework.db.PageResult;
import com.gcloud.framework.db.dao.impl.JdbcBaseDaoImpl;
import com.gcloud.framework.db.jdbc.annotation.Jdbc;
import com.gcloud.header.compute.enums.ComputeNodeState;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;
/**
Copyright (c) [2020] [G-CLOUD TECHNOLOGY] [G-Cloud 8.0] is licensed under the Mulan PSL v1.
You can use this software according to the terms and conditions of the Mulan PSL v1. You may obtain
a copy of Mulan PSL v1 at: http://license.coscl.org.cn/MulanPSL THIS SOFTWARE IS PROVIDED ON AN 
"AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 
TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the Mulan PSL v1 for more details.
 */




@Jdbc("controllerJdbcTemplate")
@Repository
public class ComputeNodeDao extends JdbcBaseDaoImpl<ComputeNode, Integer> {

	public void updateBatch(String whereField, List<String> ids,
							String setField, Object value) {
		if (ids.size() == 0) {
			return;
		}
		StringBuffer sb = new StringBuffer();
		sb.append("UPDATE gc_compute_nodes SET `");
		sb.append(setField);
		sb.append("` = '");
		sb.append(value);
		sb.append("'  WHERE ");
		int l = ids.size();
		Object[] os = new Object[l];
		for (int i = 0; i < l; i++) {
			if (i > 0) {
				sb.append(" OR ");
			}
			sb.append(" `");
			sb.append(whereField);
			sb.append("` = ? ");

			os[i] = ids.get(i);
		}
		jdbcTemplate.update(sb.toString(), os);
	}



	public <E> PageResult<E> page(DescribeNodesParams params, Class<E> clazz) {
		StringBuffer sql = new StringBuffer();
		List<Object> values = new ArrayList<>();

		sql.append("select n.*, z.name zone_name from gc_compute_nodes n left join gc_zones z on n.zone_id = z.id where 1 = 1");
		if(StringUtils.isNotBlank(params.getZoneId())){
			sql.append(" and (zone_id = ?");
			values.add(params.getZoneId());
			
			if(params.getIncludeNoZone() != null && params.getIncludeNoZone()){
				sql.append(" or zone_id is null or zone_id = '')");
			}else {
				sql.append(" )");
			}
			
		}else{
			if(params.getZone() != null){
				if(params.getZone()){
					sql.append(" and zone_id is not null and zone_id != ''");
				}else{
					sql.append(" and (zone_id is null or zone_id = '')");
				}
			}
			if(params.getIncludeNoZone() != null && params.getIncludeNoZone()){
				sql.append(" and (zone_id is null or zone_id = '')");
			}
		}
		
		if(StringUtils.isNotBlank(params.getKey())) {
			sql.append(" and (hostname like concat('%', ?, '%') or node_ip like concat('%', ?, '%') or type like concat('%', ?, '%')) ");
			values.add(params.getKey());
			values.add(params.getKey());
			values.add(params.getKey());
		}

		if(params.getState() != null){
			sql.append(" and n.state = ?");
			values.add(params.getState());
		}


		sql.append(" order by n.state desc, n.hostname");

		return findBySql(sql.toString(), values, params.getPageNumber(), params.getPageSize(), clazz);
	}

	public <E> List<E> computeNodeTotalResource(Class<E> clazz){
		StringBuffer sql = new StringBuffer();
		sql.append("SELECT hostname,cpu_total as totalCore,memory_total as totalMemory ");
		sql.append("from gc_compute_nodes ");
		sql.append("where state=1 ");
		return findBySql(sql.toString(), clazz);
	}

	public int allocateZone(String hostname, String zone){

		StringBuffer sql = new StringBuffer();
		sql.append("update gc_compute_nodes set zone_id = ? where hostname = ? and (zone_id is null or zone_id = '')");

		Object[] values = {zone, hostname};

		return this.jdbcTemplate.update(sql.toString(), values);

	}
	
	public <E> PageResult<E> pageMigrateNodes(DescribeMigrateNodesParams params, Class<E> clazz) {
		StringBuffer sql = new StringBuffer();
		List<Object> values = new ArrayList<>();
		
		sql.append("select gcn.*, gz.name as zone_name from gc_compute_nodes as gcn ");
		sql.append(" left join gc_zones gz on gcn.zone_id = gz.id ");
		sql.append(" where gcn.zone_id in ");
		sql.append(" (select gi.zone_id from gc_instances as gi where gcn.hostname != gi.hostname and gi.id = ?) ");
		sql.append(" and gcn.state = 1 ");
		values.add(params.getInstanceId());
		
		return findBySql(sql.toString(), values, params.getPageNumber(), params.getPageSize(), clazz);
	}

	public List<String> zoneNode(String zoneId, Boolean alive){
		StringBuffer sql = new StringBuffer();
		List<Object> values = new ArrayList<>();
		sql.append("select hostname from gc_compute_nodes where zone_id = ?");
		values.add(zoneId);
		if(alive != null){
			sql.append(" and state = ?");
			values.add(alive ? ComputeNodeState.CONNECTED.getValue() : ComputeNodeState.DISCONNECTED.getValue());
		}
		return this.jdbcTemplate.queryForList(sql.toString(), values.toArray(), String.class);
	}
	
	public int clearNodeZone(String hostname){

		StringBuffer sql = new StringBuffer();
		sql.append("update gc_compute_nodes set zone_id = '' where hostname = ?");

		Object[] values = {hostname};

		return this.jdbcTemplate.update(sql.toString(), values);

	}
}